﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="CuitHtmlTable.cs" company="">
//   
// </copyright>
// <summary>
//   The cuit html table search options.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace UITest.CUIT.CuitControls.HtmlControls
{
    using System;

    using Microsoft.VisualStudio.TestTools.UITesting;
    using Microsoft.VisualStudio.TestTools.UITesting.HtmlControls;

    /// <summary>
    ///     The cuit html table search options.
    /// </summary>
    public enum CuitHtmlTableSearchOptions
    {
        /// <summary>
        ///     The normal.
        /// </summary>
        Normal, 

        /// <summary>
        ///     The normal tight.
        /// </summary>
        NormalTight, 

        /// <summary>
        ///     The greedy.
        /// </summary>
        Greedy, 

        /// <summary>
        ///     The starts with.
        /// </summary>
        StartsWith, 

        /// <summary>
        ///     The ends with.
        /// </summary>
        EndsWith
    }

    /// <summary>
    ///     The AST html table.
    /// </summary>
    public class CuitHtmlTable : CuitHtmlControl<HtmlTable>
    {
        #region Constructors and Destructors

        /// <summary>
        ///     Initializes a new instance of the <see cref="CuitHtmlTable" /> class.
        /// </summary>
        public CuitHtmlTable()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CuitHtmlTable"/> class.
        /// </summary>
        /// <param name="testControl">
        /// The test control.
        /// </param>
        public CuitHtmlTable(UITestControl testControl)
            : base(testControl)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CuitHtmlTable"/> class.
        /// </summary>
        /// <param name="testControl">
        /// The test control.
        /// </param>
        /// <param name="searchProperties">
        /// The search properties.
        /// </param>
        public CuitHtmlTable(UITestControl testControl, string searchProperties)
            : base(testControl, searchProperties)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CuitHtmlTable"/> class.
        /// </summary>
        /// <param name="testControl">
        /// The test control.
        /// </param>
        /// <param name="searchProperties">
        /// The search properties.
        /// </param>
        /// <param name="filterProperties">
        /// The filter properties.
        /// </param>
        public CuitHtmlTable(UITestControl testControl, string searchProperties, string filterProperties)
            : base(testControl, searchProperties, filterProperties)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CuitHtmlTable"/> class.
        /// </summary>
        /// <param name="wrappedControl">
        /// The wrapped control.
        /// </param>
        /// <param name="searchProperties">
        /// The search properties.
        /// </param>
        public CuitHtmlTable(ICuitControlBase wrappedControl, string searchProperties)
            : base(wrappedControl, searchProperties)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="CuitHtmlTable"/> class.
        /// </summary>
        /// <param name="wrappedControl">
        /// The wrapped control.
        /// </param>
        /// <param name="searchProperties">
        /// The search properties.
        /// </param>
        /// <param name="filterProperties">
        /// The filter properties.
        /// </param>
        public CuitHtmlTable(ICuitControlBase wrappedControl, string searchProperties, string filterProperties)
            : base(wrappedControl, searchProperties, filterProperties)
        {
        }

        #endregion

        #region Public Properties

        /// <summary>
        ///     Gets the column count.
        /// </summary>
        public int ColumnCount
        {
            get
            {
                this._control.WaitForControlReady();
                return this._control.ColumnCount;
            }
        }

        /// <summary>
        ///     Gets the row count.
        /// </summary>
        public int RowCount
        {
            get
            {
                this._control.WaitForControlReady();
                return this._control.RowCount;
            }
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The click on cell.
        /// </summary>
        /// <param name="rowIndex">
        /// The row index.
        /// </param>
        /// <param name="columnIndex">
        /// The column index.
        /// </param>
        public void ClickOnCell(int rowIndex, int columnIndex)
        {
            var cell = new CuitHtmlCell(this._control, rowIndex, columnIndex);
            cell.Click();
        }

        /// <summary>
        /// The click on header cell.
        /// </summary>
        /// <param name="rowIndex">
        /// The row index.
        /// </param>
        /// <param name="columnIndex">
        /// The column index.
        /// </param>
        public void ClickOnHeaderCell(int rowIndex, int columnIndex)
        {
            var cell = new CuitHtmlHeaderCell(this._control, rowIndex, columnIndex);
            cell.Click();
        }

        /// <summary>
        /// The click on header cell.
        /// </summary>
        /// <param name="headerName">
        /// The header name.
        /// </param>
        public void ClickOnHeaderCell(string headerName)
        {
            var cell = new CuitHtmlHeaderCell(this._control, "InnerText=" + headerName);
            cell.Click();
        }

        /// <summary>
        /// The double click on cell.
        /// </summary>
        /// <param name="rowIndex">
        /// The row index.
        /// </param>
        /// <param name="columnIndex">
        /// The column index.
        /// </param>
        public void DoubleClickOnCell(int rowIndex, int columnIndex)
        {
            var cell = new CuitHtmlCell(this._control, rowIndex, columnIndex);
            cell.DoubleClick();
        }

        /// <summary>
        /// The find row.
        /// </summary>
        /// <param name="columnIndex">
        /// The column Index.
        /// </param>
        /// <param name="valueToSearch">
        /// The value To Search.
        /// </param>
        /// <param name="option">
        /// The option.
        /// </param>
        /// <param name="startingRowIndex">
        /// The starting Row Index.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public int FindRow(
            int columnIndex, 
            string valueToSearch, 
            CuitHtmlTableSearchOptions option, 
            int startingRowIndex = 0)
        {
            this._control.WaitForControlReady();
            int rowIndex = -1;

            /* //too slow
            foreach (UITestControl control in this._control.Rows)
            {
                // control could be of ControlType.RowHeader or ControlType.Row
                rowCount++;

                int colCount = -1;

                foreach (HtmlControl cell in control.GetChildren())
                {
                    // Cells could be a collection of HtmlCell and HtmlHeaderCell controls
                    colCount++;
                    bool searchOptionResult = false;
                    if (colCount == columnIndex)
                    {
                        if (!string.IsNullOrEmpty(cell.InnerText))
                        {
                            if (option == CuitHtmlTableSearchOptions.Normal)
                            {
                                searchOptionResult = valueToSearch == cell.InnerText;
                            }
                            else if (option == CuitHtmlTableSearchOptions.NormalTight)
                            {
                                searchOptionResult = valueToSearch == cell.InnerText.Trim();
                            }
                            else if (option == CuitHtmlTableSearchOptions.StartsWith)
                            {
                                searchOptionResult = cell.InnerText.StartsWith(valueToSearch);
                            }
                            else if (option == CuitHtmlTableSearchOptions.EndsWith)
                            {
                                searchOptionResult = cell.InnerText.EndsWith(valueToSearch);
                            }
                            else if (option == CuitHtmlTableSearchOptions.Greedy)
                            {
                                searchOptionResult = cell.InnerText.IndexOf(valueToSearch) > -1;
                            }
                        }

                        if (searchOptionResult)
                        {
                            rowIndex = rowCount;
                            break;
                        }
                    }
                }

                if (rowIndex > -1)
                {
                    break;
                }
             
            }
             */
            var tempHtmlCellControl = new CuitHtmlCell(this._control, "InnerText~" + valueToSearch);
            UITestControlCollection htmlcellControls = tempHtmlCellControl.FindMatchingControls();

            foreach (UITestControl htmlcellControl in htmlcellControls)
            {
                if (int.Parse(htmlcellControl.GetProperty("ColumnIndex").ToString()) == columnIndex)
                {
                    if (option == CuitHtmlTableSearchOptions.Normal)
                    {
                        if (htmlcellControl.GetProperty("InnerText").ToString().Equals(valueToSearch))
                        {
                            rowIndex = int.Parse(htmlcellControl.GetProperty("RowIndex").ToString());
                            if (rowIndex >= startingRowIndex)
                            {
                                return rowIndex;
                            }
                        }
                    }
                    else if (option == CuitHtmlTableSearchOptions.NormalTight)
                    {
                        if (htmlcellControl.GetProperty("InnerText").ToString().Trim().Equals(valueToSearch))
                        {
                            rowIndex = int.Parse(htmlcellControl.GetProperty("RowIndex").ToString());
                            if (rowIndex >= startingRowIndex)
                            {
                                return rowIndex;
                            }
                        }
                    }
                    else if (option == CuitHtmlTableSearchOptions.StartsWith)
                    {
                        if (htmlcellControl.GetProperty("InnerText").ToString().StartsWith(valueToSearch))
                        {
                            rowIndex = int.Parse(htmlcellControl.GetProperty("RowIndex").ToString());
                            if (rowIndex >= startingRowIndex)
                            {
                                return rowIndex;
                            }
                        }
                    }
                    else if (option == CuitHtmlTableSearchOptions.EndsWith)
                    {
                        if (htmlcellControl.GetProperty("InnerText").ToString().EndsWith(valueToSearch))
                        {
                            rowIndex = int.Parse(htmlcellControl.GetProperty("RowIndex").ToString());
                            if (rowIndex >= startingRowIndex)
                            {
                                return rowIndex;
                            }
                        }
                    }
                    else if (option == CuitHtmlTableSearchOptions.Greedy)
                    {
                        if (htmlcellControl.GetProperty("InnerText").ToString().IndexOf(valueToSearch) > -1)
                        {
                            rowIndex = int.Parse(htmlcellControl.GetProperty("RowIndex").ToString());
                            if (rowIndex >= startingRowIndex)
                            {
                                return rowIndex;
                            }
                        }
                    }
                }
            }

            return rowIndex;
        }

        /// <summary>
        /// The find row.
        /// </summary>
        /// <param name="headerName">
        /// The header name.
        /// </param>
        /// <param name="valueToSearch">
        /// The value to search.
        /// </param>
        /// <param name="option">
        /// The option.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public int FindRow(string headerName, string valueToSearch, CuitHtmlTableSearchOptions option)
        {
            return this.FindRow(this.GetColumnIndex(headerName), valueToSearch, option);
        }

        /// <summary>
        /// The get cell.
        /// </summary>
        /// <param name="rowIndex">
        /// The row index.
        /// </param>
        /// <param name="colIndex">
        /// The col index.
        /// </param>
        /// <returns>
        /// The <see cref="ICuitControlBase"/>.
        /// </returns>
        /// <exception cref="Exception">
        /// </exception>
        public ICuitControlBase GetCell(int rowIndex, int colIndex)
        {
            HtmlControl control = this._control.GetCell(rowIndex, colIndex);
            ICuitControlBase _con = null;

            if (control.GetType() == typeof(HtmlCell))
            {
                _con = new CuitHtmlCell();
            }
            else if (control.GetType() == typeof(HtmlHeaderCell))
            {
                _con = new CuitHtmlHeaderCell();
            }
            else
            {
                throw new Exception(string.Format("WrapUtil: '{0}' not supported", control.GetType().Name));
            }

            _con.WrapReady(control);

            return _con;
        }

        /// <summary>
        /// The get cell child.
        /// </summary>
        /// <param name="rowIndex">
        /// The row index.
        /// </param>
        /// <param name="columnName">
        /// The column name.
        /// </param>
        /// <typeparam name="T2">
        /// </typeparam>
        /// <returns>
        /// The <see cref="T2"/>.
        /// </returns>
        public T2 GetCellChild<T2>(int rowIndex, string columnName) where T2 : ICuitHtmlControl
        {
            return this.GetCellChild<T2>(rowIndex, columnName, string.Empty);
        }

        /// <summary>
        /// The get cell child.
        /// </summary>
        /// <param name="rowIndex">
        /// The row index.
        /// </param>
        /// <param name="columnName">
        /// The column name.
        /// </param>
        /// <param name="searchProperties">
        /// The search properties.
        /// </param>
        /// <typeparam name="T2">
        /// </typeparam>
        /// <returns>
        /// The <see cref="T2"/>.
        /// </returns>
        public T2 GetCellChild<T2>(int rowIndex, string columnName, string searchProperties) where T2 : ICuitHtmlControl
        {
            int colIndex = this.GetColumnIndex(columnName);
            var control = this.GetCellChild<T2>(rowIndex, colIndex, searchProperties);
            return control;
        }

        /// <summary>
        /// The get cell child.
        /// </summary>
        /// <param name="rowIndex">
        /// The row index.
        /// </param>
        /// <param name="colIndex">
        /// The col index.
        /// </param>
        /// <typeparam name="T2">
        /// </typeparam>
        /// <returns>
        /// The <see cref="T2"/>.
        /// </returns>
        public T2 GetCellChild<T2>(int rowIndex, int colIndex) where T2 : ICuitHtmlControl
        {
            return this.GetCellChild<T2>(rowIndex, colIndex, string.Empty);
        }

        /// <summary>
        /// The get cell child.
        /// </summary>
        /// <param name="rowIndex">
        /// The row index.
        /// </param>
        /// <param name="colIndex">
        /// The col index.
        /// </param>
        /// <param name="searchProperties">
        /// The search Properties.
        /// </param>
        /// <typeparam name="T2">
        /// </typeparam>
        /// <returns>
        /// The <see cref="T2"/>.
        /// </returns>
        /// <exception cref="Exception">
        /// </exception>
        public T2 GetCellChild<T2>(int rowIndex, int colIndex, string searchProperties) where T2 : ICuitHtmlControl
        {
            this._control.WaitForControlReady();

            // HtmlControl htmlCell = this._control.GetCell(rowIndex, colIndex);
            var htmlCell = new CuitHtmlCell(this._control, rowIndex, colIndex);

            object htmlControl;

            if (typeof(T2) == typeof(CuitHtmlButton))
            {
                htmlControl = new CuitHtmlButton(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlCheckBox))
            {
                htmlControl = new CuitHtmlCheckBox(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlComboBox))
            {
                htmlControl = new CuitHtmlComboBox(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlDiv))
            {
                htmlControl = new CuitHtmlDiv(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlEdit))
            {
                htmlControl = new CuitHtmlEdit(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlEditableDiv))
            {
                htmlControl = new CuitHtmlEditableDiv(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlEditUnderDiv))
            {
                htmlControl = new CuitHtmlEditUnderDiv(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlFileInput))
            {
                htmlControl = new CuitHtmlFileInput(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlHyperLink))
            {
                htmlControl = new CuitHtmlHyperLink(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlImage))
            {
                htmlControl = new CuitHtmlImage(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlInputButton))
            {
                htmlControl = new CuitHtmlInputButton(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlLabel))
            {
                htmlControl = new CuitHtmlLabel(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlList))
            {
                htmlControl = new CuitHtmlList(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlRadioButton))
            {
                htmlControl = new CuitHtmlRadioButton(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlSpan))
            {
                htmlControl = new CuitHtmlSpan(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlEditableSpan))
            {
                htmlControl = new CuitHtmlEditableSpan(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlTable))
            {
                htmlControl = new CuitHtmlTable(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlCell))
            {
                htmlControl = new CuitHtmlCell(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlHeaderCell))
            {
                htmlControl = new CuitHtmlHeaderCell(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlRow))
            {
                htmlControl = new CuitHtmlRow(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlTextArea))
            {
                htmlControl = new CuitHtmlTextArea(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlIFrame))
            {
                htmlControl = new CuitHtmlIFrame(htmlCell, searchProperties);
            }
            else if (typeof(T2) == typeof(CuitHtmlCustom))
            {
                htmlControl = new CuitHtmlCustom(htmlCell, searchProperties);
            }
            else
            {
                throw new Exception(string.Format("CreateControls: '{0}' not supported", typeof(T2).Name));
            }

            return (T2)htmlControl;
        }

        /// <summary>
        /// The get cell value.
        /// </summary>
        /// <param name="rowIndex">
        /// The row index.
        /// </param>
        /// <param name="colIndex">
        /// The col index.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public string GetCellValue(int rowIndex, int colIndex)
        {
            return this._control.GetCell(rowIndex, colIndex).InnerText;
        }

        /// <summary>
        ///     The get column headers.
        /// </summary>
        /// <returns>
        ///     The <see cref="string[]" />.
        /// </returns>
        public string[] GetColumnHeaders()
        {
            string[] retArray;
            UITestControlCollection rows = this._control.Rows;
            if ((rows != null) && (rows.Count > 0))
            {
                if ((rows[0] != null) && (rows[0].ControlType == ControlType.RowHeader))
                {
                    UITestControlCollection headers = rows[0].GetChildren();
                    retArray = new string[headers.Count];
                    for (int i = 0; i < retArray.Length; i++)
                    {
                        retArray[i] = (string)headers[i].GetProperty("Value");
                    }

                    return retArray;
                }
            }

            return null;
        }

        /// <summary>
        /// The get column index.
        /// </summary>
        /// <param name="columnName">
        /// The column name.
        /// </param>
        /// <returns>
        /// The <see cref="int"/>.
        /// </returns>
        public int GetColumnIndex(string columnName)
        {
            this._control.WaitForControlReady();
            var htmlHeaderCell = new CuitHtmlHeaderCell(this._control, "InnerText=" + columnName);

            /*
            string[] columnuHeaders = this._control.GetColumnNames();
            int columnIndex = -1;
            for (int i = 0; i < columnuHeaders.Count(); i++)
            {
                if (columnuHeaders[i] == columnName)
                {
                    columnIndex = i;
                    break;
                }
            }
             */
            int columnIndex = -1;
            columnIndex = int.Parse(htmlHeaderCell.GetProperty("ColumnIndex").ToString());

            return columnIndex;
        }

        /// <summary>
        ///     The get row headers.
        /// </summary>
        /// <returns>
        ///     The <see cref="string[]" />.
        /// </returns>
        public string[] GetRowHeaders()
        {
            string[] retArray;
            UITestControlCollection rows = this._control.Rows;
            if ((rows != null) && (rows.Count > 0))
            {
                CuitHtmlHeaderCell htmlHeaderCell;
                retArray = new string[rows.Count];
                for (int i = 0; i < retArray.Length; i++)
                {
                    htmlHeaderCell = new CuitHtmlHeaderCell(this._control, "RowIndex=" + i);

                    retArray[i] = htmlHeaderCell.InnerText;
                }

                return retArray;
            }

            return null;
        }

        #endregion
    }
}